//
//  NSStringAdditions.m
//  MailDelivery
//
//  Created by Dante Palacios on 26/08/09.
//  Copyright 2008 Dante Palacios. All rights reserved.
//

#import "NSStringAdditions.h"
#import "NSAttributedStringAdditions.h"
#import "NSDataAdditions.h"

#import "Funtions.h"

#define IsPrintable(c) (isascii(c) && isprint(c))

@implementation NSString(NSStringMailDeliveryEmailAdditions)

- (NSString *)displayName 
{
	if (![self containsString:@"<"]) return nil;
	
	NSScanner *scanner = [NSScanner scannerWithString:self];
	NSString *displayName = @"";
	@try {
		[scanner scanUpToString:@"<" intoString:&displayName];	
	}
	@catch (NSException * e) {
		return nil;
	}
	return [displayName stringByTrimmingWhiteSpaces];
}

- (NSString *)address 
{
	if (![self containsString:@"@"]) return nil;
    
	NSString *email = self;
	NSArray *emails = [[self stringByReplacingOccurrencesOfString:@" " withString:@""] componentsSeparatedByString:@","];
	if (emails.count) 
	{
		email = [emails objectAtIndex:0];
	}
	
	if ([email containsString:@"<"]) 
	{
		NSScanner *scanner = [NSScanner scannerWithString:email];
		NSString *address = @"";
		@try {
			[scanner scanUpToString:@"<" intoString:nil];
			[scanner setScanLocation:[scanner scanLocation] + 1];
			[scanner scanUpToString:@">" intoString:&address];	
		}
		@catch (NSException * e) {
			return nil;
		}
		return [address stringByTrimmingWhiteSpaces];
	}
	
	return [self stringByTrimmingWhiteSpaces];
}

- (NSString *)domain 
{
	NSString *address = self.address;
	if (!address.length) return nil;
	
	NSString *domain = [[address componentsSeparatedByString:@"@"] lastObject];
	NSArray *components = [domain componentsSeparatedByString:@"."];
	if ([components count] > 2) 
	{
		return [NSString stringWithFormat:@"%@.%@", [components objectAtIndex:0], [components objectAtIndex:1]];
	}
	
	return domain;
}

- (NSString *)hostName 
{
	NSString *domain = self.domain;
	if (!domain.length) return nil;
	
	NSString *hostName = [NSString stringWithFormat:@"smtp.%@", domain];
	if ([domain containsString:@"yahoo"])
		hostName = [NSString stringWithFormat:@"smtp.mail.%@", domain];
	else if ([domain containsString:@"msn"] || [domain containsString:@"hotmail"])
		hostName = @"smtp.live.com";
	
	return hostName;
}

- (NSString *)userName 
{
	NSString *address = self.address;
	if (!address.length) return nil;
	
	return [[address componentsSeparatedByString:@"@"] objectAtIndex:0];
}

@end

@implementation NSString(NSStringMailDeliveryEncodingAdditions)

+ (NSStringEncoding)encodingForString:(NSString *)string 
{
	NSStringEncoding encoding[] = { 
		NSASCIIStringEncoding, 
		NSISOLatin1StringEncoding,
		NSISOLatin2StringEncoding, 
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin3),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin4),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinCyrillic),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinArabic),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinGreek),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinHebrew),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin5),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin6),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinThai),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin7),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin8),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin9),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingKOI8_R),
		CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingHZ_GB_2312),
		NSISO2022JPStringEncoding,
		NSUTF8StringEncoding,
	0 };
	
	NSInteger i;
	for (i = 0; encoding[i]; i++) 
	{
		if ([string canBeConvertedToEncoding:encoding[i]]) 
		{
			return encoding[i];
		}
	}
	
	// Couldn't find a suitable encoding - return something "meaningful"
	return NSUTF8StringEncoding;
}

+ (NSString *)mimeNameOfStringEncoding:(NSStringEncoding)encoding 
{
	NSDictionary *mimeNames = [NSDictionary dictionaryWithObjectsAndKeys:
							   @"US-ASCII", [NSString stringWithFormat:@"%d", NSASCIIStringEncoding],
							   @"ISO-8859-1", [NSString stringWithFormat:@"%d", NSISOLatin1StringEncoding],
							   @"ISO-8859-2", [NSString stringWithFormat:@"%d", NSISOLatin2StringEncoding],
							   @"ISO-8859-3", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin3)],
							   @"ISO-8859-4", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin4)],
							   @"ISO-8859-5", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinCyrillic)],
							   @"ISO-8859-6", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinArabic)],
							   @"ISO-8859-7", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinGreek)],
							   @"ISO-8859-8", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinHebrew)],
							   @"ISO-8859-9", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin5)],
							   @"ISO-8859-10", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin6)],
							   @"ISO-8859-11", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinThai)],
							   @"ISO-8859-13", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin7)],
							   @"ISO-8859-14", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin8)],
							   @"ISO-8859-15", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin9)],
							   @"KOI8-R", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingKOI8_R)],
							   @"HZ-GB-2312", [NSString stringWithFormat:@"%d", CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingHZ_GB_2312)],
							   @"ISO-2022-JP", [NSString stringWithFormat:@"%d", NSISO2022JPStringEncoding],
							   @"UTF-8", [NSString stringWithFormat:@"%d", NSUTF8StringEncoding],
							   nil];
	
	return [mimeNames objectForKey:[NSString stringWithFormat:@"%d", encoding]];
}

@end


@interface _MDStringHelper : NSObject
{
	NSString *_plainText;
}

- (NSString *)convertHTMLStringToPlainText:(NSString *)HTMLString;

@end

@implementation _MDStringHelper

- (void)dealloc
{
	[_plainText release], _plainText = nil;
	
	[super dealloc];
}

- (NSString *)convertHTMLStringToPlainText:(NSString *)HTMLString; 
{
	NSString *value = nil;
	
	@synchronized(self) 
	{
		if (!_plainText) 
		{
			NSStringEncoding encoding = [HTMLString encoding];
			NSData *data = [HTMLString dataUsingEncoding:encoding allowLossyConversion:YES];
			NSAttributedString *attributedString = [[NSAttributedString alloc] initWithHTML:data options:[NSDictionary dictionaryWithObjectsAndKeys:NSHTMLTextDocumentType, NSDocumentTypeDocumentAttribute, [NSNumber numberWithUnsignedInteger:encoding], NSCharacterEncodingDocumentOption, [NSArray arrayWithObjects:@"DOCTYPE", @"XML", nil], NSExcludedElementsDocumentAttribute, nil] documentAttributes:NULL];
			if (attributedString) 
			{
				_plainText = [[attributedString plainText] copy];
				
				[attributedString release];
			}
		}
		
		if (_plainText) 
		{
			value = [[_plainText copy] autorelease];
		}
	}
	
	return value;
}

@end

@implementation NSString(NSStringMailDeliveryAdditions)

+ (NSString *)stringWithUUID
{
	CFUUIDRef uuidObj = CFUUIDCreate(kCFAllocatorDefault);
	CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, uuidObj);
	CFRelease(uuidObj);
	return [NSMakeCollectable(uuidString) autorelease];
}

- (NSString *)stringByRemovingHTML;
{
	if (!self.length) return self;
	
	_MDStringHelper *helper = [[_MDStringHelper alloc] init];
	if (![[NSThread currentThread] isEqual:[NSThread mainThread]])
	{
		[helper performSelectorOnMainThread:@selector(convertHTMLStringToPlainText:) withObject:self waitUntilDone:YES];
	}
	
	NSString *string = [helper convertHTMLStringToPlainText:self];
	
	[helper release];
	
	return string;
}

- (NSString *)stringByTrimmingWhiteSpaces 
{
	return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}

- (NSString *)stringWithCRLFLineBreaks
{
	NSMutableString *string = [[NSMutableString alloc] init];
	NSScanner *scanner = [NSScanner scannerWithString:self];
	while (![scanner isAtEnd])
	{
		NSString *line = nil;
		if ([scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&line]) 
		{
			[string appendFormat:@"%@\r\n", [line stringByTrimmingCharactersInSet:[NSCharacterSet illegalCharacterSet]]];
		}
	}
	
	return [string autorelease];
}

- (NSString *)quotedPrintableString 
{
	NSStringEncoding encoding = self.encoding;
	NSData *data = [self dataUsingEncoding:encoding allowLossyConversion:YES];
	NSData *quotedData = [data encodeQuotedPrintableWithLineLength:100 inHeader:NO];
	return [[[NSString alloc] initWithBytes:quotedData.bytes length:quotedData.length encoding:encoding] autorelease];
}

- (BOOL)isCaseInsensitiveEqualToString:(NSString *)string
{
	return ([self caseInsensitiveCompare:string] == NSOrderedSame);
}

- (BOOL)containsString:(NSString *)string;
{
	return !self.length ? NO : [self rangeOfString:string].location != NSNotFound;
}

- (NSStringEncoding)encoding;
{
	return [[self class] encodingForString:self];
}

@end